#include "stdafx.h"
#include "Model.h"
#include "ImageTGA.h"

void Model::Init(char *fileNFG, char *fileTGA)
{
	cObject::Init(GL_TEXTURE_2D, &fileTGA, 1, fileNFG);

	ImageTGA *src = new ImageTGA();
	src->szTexSrc = LoadTGA("../Resources/Textures/NormalMap.tga", &src->iWidth, &src->iHeight, &src->iBPP);
	glGenTextures(1, &m_uiNormMapTextureID);
	glBindTexture(GL_TEXTURE_2D, m_uiNormMapTextureID);
	if(src->iBPP == 24)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, src->iWidth, src->iHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, src->szTexSrc);
	}
	else if(src->iBPP == 32)
	{
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src->iWidth, src->iHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, src->szTexSrc);
	}
	else
	{
		return ;
	}
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glBindTexture(GL_TEXTURE_2D, 0);
	SAFE_DEL(src);

	//Create model shader
	m_Shader = ModelShader();
	m_Shader.Init("../Resources/Shaders/ModelShaderVS.vs", "../Resources/Shaders/ModelShaderFS.fs");
}


void Model::Draw(ESContext *esContext)
{
	glUseProgram(m_Shader.program);

	glBindBuffer(GL_ARRAY_BUFFER, m_Model->GetVertexID());
	int size;
	glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
	size /= sizeof(Vertex);
	if(m_Shader.VertPosition != -1)
	{
		glEnableVertexAttribArray(m_Shader.VertPosition);
		glVertexAttribPointer(m_Shader.VertPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
	}
	if(m_Shader.VertTexCoord != -1)
	{
		glEnableVertexAttribArray(m_Shader.VertTexCoord);
		glVertexAttribPointer(m_Shader.VertTexCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (char*)0 + sizeof(Vector3));
	}
	if(m_Shader.VertNorm != -1)
	{
		glEnableVertexAttribArray(m_Shader.VertNorm);
		glVertexAttribPointer(m_Shader.VertNorm, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (char*)0 + sizeof(Vector3) + sizeof(Vector2));
	}
	if(m_Shader.VertBiNorm != -1)
	{
		glEnableVertexAttribArray(m_Shader.VertBiNorm);
		glVertexAttribPointer(m_Shader.VertBiNorm, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (char*)0 + sizeof(Vector3)*2 + sizeof(Vector2));
	}
	if(m_Shader.VertTangent != -1)
	{
		glEnableVertexAttribArray(m_Shader.VertTangent);
		glVertexAttribPointer(m_Shader.VertTangent, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (char*)0 + sizeof(Vector3)*3 + sizeof(Vector2));
	}

	if(m_Shader.WVPMatrix != -1)
	{
		Matrix maView = Globals::MainCamera->GetVPMatrix();
		glUniformMatrix4fv(m_Shader.WVPMatrix, 1, GL_FALSE, (GLfloat*)&(m_maLocalW*maView).m[0][0]);
	}
	if(m_Shader.WMatrix != -1)
	{
		glUniformMatrix4fv(m_Shader.WMatrix, 1, GL_FALSE, (GLfloat*)&m_maLocalW.m[0][0]);
	}

	if(m_Shader.CameraPosition != -1)
	{
		Vector3 cameraPosition = Globals::MainCamera->GetPosition();
		glUniform3f(m_Shader.CameraPosition, cameraPosition.x, cameraPosition.y, cameraPosition.z);
	}
	if(m_Shader.LightPosition != -1)
	{
		glUniform3f(m_Shader.LightPosition, 0.0f, 150.0f, 50.0f);
	}
	if(m_Shader.ObjTexture != -1)
	{
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, m_Texture->GetTextureID()[0]);
		glUniform1i(m_Shader.ObjTexture, 0);
	}
	if(m_Shader.NormMapTexture != -1)
	{
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, m_uiNormMapTextureID);
		glUniform1i(m_Shader.NormMapTexture, 0);
	}

	if(m_Shader.Step != -1)
	{
		float k = 0.5f;
		float x = 1.0f / Globals::screenWidth;
		float y = 1.0f / Globals::screenHeight;
		float z = sqrt(2.0f) / 2.0f * x;
		float w = sqrt(2.0f) / 2.0f * y;
		glUniform4f(m_Shader.Step, x*k, y*k, z*k, w*k);
	}

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Model->GetIndiceID());
	glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
	size /= sizeof(GLuint);
	glDrawElements(GL_TRIANGLES, m_Model->GetIndiceNumber(), GL_UNSIGNED_INT, 0);

	glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	glBindTexture(GL_TEXTURE_2D, 0);
}

Model::~Model()
{
	SAFE_DEL(m_Texture);
}